#include "api.hpp"
#include <iostream>
#include <map>
#include <memory>
#include <new>
#include <string>
#include <type_traits>
#include <vector>

void test1();
void test2();
void test3();
void test4();
void test5();
void test6();
void test7();
void test8();
void test9();
void test10();
void test() {
  test10();
  std::cout << "hello, world~" << std::endl;
}

// from 《rust编程之道》 章节5
void test1() {
  std::unique_ptr<int> orig(new int(5));
  std::cout << *orig << std::endl;
  auto stolen = std::move(orig);
  std::cout << *orig << std::endl;
}

class my_string {
public:
  std::string _str;
  my_string() : _str(std::string()) {
    std::cout << __FUNCTION__ << ":" << __LINE__ << std::endl;
  }
  my_string(std::string s) : _str(s) {
    std::cout << __FUNCTION__ << ":" << __LINE__ << std::endl;
  }
  my_string(const my_string &o) : _str(o._str) {
    std::cout << __FUNCTION__ << ":" << __LINE__ << std::endl;
  }
  my_string(my_string &&o) : _str(std::move(o._str)) {
    std::cout << __FUNCTION__ << ":" << __LINE__ << std::endl;
  }
  my_string &operator=(const my_string &o) {
    std::cout << __FUNCTION__ << ":" << __LINE__ << std::endl;
    if (this != &o) {
      _str = std::move(o._str);
    }
    return *this;
  }
  my_string &operator=(my_string &&o) {
    std::cout << __FUNCTION__ << ":" << __LINE__ << std::endl;
    if (this != &o) {
      _str = o._str;
    }
    return *this;
  }
  virtual ~my_string() {
    std::cout << __FUNCTION__ << ":" << __LINE__ << std::endl;
  }
};

std::string output() { return std::move(std::string("888888")); }
void _invoke(std::string &&s) { std::cout << s.c_str() << std::endl; }

void test2() {
  // _invoke(std::forward(output()));
  _invoke(output());
}

my_string output_my_string() { return my_string(std::string("my_string")); }
// 这个函数本身写法就有问题
my_string &&output_my_string_move() {
  // return my_string(std::string("my_string"));
  return std::move(my_string(std::string("my_string")));
}

my_string output_my_string_move_2() {
  return std::move(my_string(std::string("my_string")));
}
void _my_invoke_move(my_string &&s) {
  std::cout << s._str.c_str() << std::endl;
}
void _my_invoke_ref(my_string &s) { std::cout << s._str.c_str() << std::endl; }
void _my_invoke(my_string s) { std::cout << s._str.c_str() << std::endl; }

void test3() {
  {
      // _my_invoke(output_my_string());// ok, 普通构造一次
      // my_string tmp = output_my_string();
      // _my_invoke(tmp);

      // _my_invoke_move(output_my_string_move());// error
      // _my_invoke_ref(output_my_string());// error

      // `output_my_string_move()`
      // 返回对象发生了析构，发生在移动复制之前，所以返回空对象 my_string tmp =
      // output_my_string_move(); std::cout << tmp._str.c_str() << std::endl;

      // `output_my_string_move_2()`内部发生了返回对象移动复制、返回对象析构
      // my_string tmp = output_my_string_move_2();
      // std::cout << tmp._str.c_str() << std::endl;

  }

  {
      // my_string tmp = output_my_string();
      // _my_invoke_move(tmp);
      // _my_invoke_move(std::forward<my_string&&>(tmp));
      // _my_invoke_ref(tmp);
      // _my_invoke_ref(std::forward<my_string&>(tmp));
      // _my_invoke(tmp);

      // my_string&& tmp_r_ref = output_my_string();
      // _my_invoke_move(tmp_r_ref);// error
      // _my_invoke_move(std::forward<my_string&&>(tmp_r_ref));
      // _my_invoke_ref(tmp_r_ref);
      // _my_invoke_ref(std::forward<my_string&>(tmp_r_ref));
      // _my_invoke(tmp_r_ref);
  }

  {
      // my_string s = my_string(std::string("my_string"));
      // my_string q = std::forward<my_string&>(s);
      // my_string v = std::forward<my_string&&>(s);
      // std::cout << "s:" << s._str.c_str() << std::endl;
      // std::cout << "q:" << q._str.c_str() << std::endl;
      // std::cout << "v:" << v._str.c_str() << std::endl;
  }

  {
    // my_string s = my_string(std::string("my_string"));
    // // my_string v = std::move<my_string&>(s);
    // my_string v = std::move(s);
    // std::cout << "s:" << s._str.c_str() << std::endl;
    // std::cout << "v:" << v._str.c_str() << std::endl;
  }
}

BaseClass::BaseClass() {
  std::cout << __FUNCTION__ << ":" << __LINE__ << std::endl;
}
BaseClass::~BaseClass() {
  std::cout << __FUNCTION__ << ":" << __LINE__ << std::endl;
  print();
}
void BaseClass::print() {
  std::cout << __FUNCTION__ << ":" << __LINE__ << std::endl;
}
void BaseClass::override_print() {
  std::cout << __FUNCTION__ << ":" << __LINE__ << std::endl;
  print();
}

DerivedClass::DerivedClass() : BaseClass() {
  std::cout << __FUNCTION__ << ":" << __LINE__ << std::endl;
}
DerivedClass::~DerivedClass() {
  std::cout << __FUNCTION__ << ":" << __LINE__ << std::endl;
  print();
}
void DerivedClass::print() {
  std::cout << __FUNCTION__ << ":" << __LINE__ << std::endl;
}
void DerivedClass::override_print() {
  std::cout << __FUNCTION__ << ":" << __LINE__ << std::endl;
  print();
}

void test4() {
  BaseClass *base = new DerivedClass();
  base->override_print();
  delete base;
}

void test5() {
  BaseClass *base = new DerivedClass();
  ((BaseClass *)base)->override_print();
  base->override_print();
  base->BaseClass::override_print();
  delete base;
}

// ref: https://zh.cppreference.com/w/cpp/types/enable_if

// 经由模板形参启用 A 的偏特化
template <class T, class Enable = void> class A {}; // 初等模板

template <class T>
class A<T, typename std::enable_if<std::is_floating_point<T>::value>::type> {
}; // 浮点类型的特化

// #if _LIBCPP_STD_VER > 11
// template <bool _Bp, class _Tp = void> using enable_if_t = typename
// enable_if<_Bp, _Tp>::type; #endif

template <class T, std::enable_if_t<std::is_floating_point_v<T>, int> = 0>
class B {};

template <class T,
          typename std::enable_if<std::is_floating_point_v<T>, int>::type = 0>
class C {};

template <class T,
          typename std::enable_if<std::is_same<T, int>::value, int>::type = 0>
class D {};

void test6() {
  // A<int>{};    // OK ：匹配初等模板
  // A<double>{}; // OK ：匹配偏特化+
  // D<int>{};    // OK
  // D<double>{}; // Error
}

template <class T, T _value> class E {
public:
  T value;
  E() : value(_value) {}
};

void test7() {
  auto e = E<int, 1>{};
  std::cout << e.value << std::endl;
}

template <class T, T _value = T()> class F {
public:
  T value;
  F() : value(_value) {}
};

void test8() {
  auto f = F<int>{};
  std::cout << f.value << std::endl;
}

struct Data {
  Data() {}
};

template <class T, typename std::is_same<Data, T>::value_type = true> class G {
public:
  // T value;
};

void test9() {
  // G<int>{};// error
  // G<double>{}; // error
  // G<Data>{}; // OK
}

template <class T> struct Value { T value; };

struct JsonNode {};
template <class _NodeType> struct JsonNodeType : public JsonNode {
  typedef _NodeType node_type;
  const std::string _type_name;
  JsonNodeType() : _type_name(std::string(typeid(node_type).name())) {}
  template <class NodeType> bool is_same() {
    return std::is_same<NodeType, node_type>::value;
  }
  const std::string &type_name() { return this->_type_name; }
};

struct Void : public JsonNodeType<Void> {};

template <class Value>
struct JsonKeyValue : public JsonNodeType<JsonKeyValue<Value>> {
  std::pair<std::string, Value> kv;
  JsonKeyValue(std::string&& key, Value&& value): kv(std::make_pair(key, value)) {

  }
};

template <class Value>
struct JsonKeyValueList : public JsonNodeType<JsonKeyValueList<Value>> {
  std::vector<Value> list;
};

template <class Value>
struct JsonKeyValueMap : public JsonNodeType<JsonKeyValueMap<Value>> {
  std::map<std::string, Value> map;
};

class JsonObject {
private:
  std::shared_ptr<JsonNode> _node_ptr;

public:
  JsonObject(/* args */) {}
  ~JsonObject() {}
  /// 转换为`json`格式字符串
  std::string to_string() { return ""; }
  /// 通过`json`格式字符串创建`json`对象
  bool from_string(const std::string &jsonObjectString) { return false; }
  template <class Value>
  bool add_child_node(const JsonNodeType<Value> &&child) {
    if (nullptr == _node_ptr.get()) {
      _node_ptr = std::make_shared<JsonNodeType<Value>>(std::move(child));
    }

    return false;
  }
  bool del_child_node(const std::string &key) { return false; }

private:
};

class JsonHelper {
private:
  /* data */
public:
  JsonHelper(/* args */) {}
  virtual ~JsonHelper() {}

public:
};

void test10() {
  JsonNodeType<std::nullptr_t> s;
  // s.type_name() = "ss";
  std::cout << s.type_name().c_str() << std::endl;
  std::cout << typeid(std::string).name() << std::endl;
  std::cout << s.is_same<nullptr_t>() << std::endl;

  // std::shared_ptr<JsonNodeType<int>> root = std::make_shared<JsonKeyValue<int>>(JsonKeyValue<int>("1", 2));
  // std::shared_ptr<JsonKeyValue<int>> tmp = std::dynamic_pointer_cast<JsonKeyValue<int>>(root);
  // std::cout << ";" << std::endl;

  // std::shared_ptr<BaseClass> test1 = std::make_shared<DerivedClass>();
  // std::shared_ptr<DerivedClass> test2 = std::dynamic_pointer_cast<DerivedClass>(test1);

  // JsonNode* root = new JsonKeyValue<int>("1", 2);
  // JsonKeyValue<int>* sub_node = dynamic_cast<JsonKeyValue<int>*>(root);

  // BaseClass* base = new DerivedClass();
  // DerivedClass* derived = dynamic_cast<DerivedClass*>(base);

  auto node = JsonKeyValue<int>("1", 2);
  auto node2 = JsonKeyValueList<JsonKeyValue<int>>();
  node2.list.push_back(node);

  /// json制作失败了
}